package com.calvin.lingting.service;

import android.app.NotificationManager;
import android.content.Context;
import android.os.Environment;
import android.os.Handler;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.widget.Toast;
import com.calvin.lib.json.JSON;
import com.calvin.lib.json.JSONArray;
import com.calvin.lib.json.JSONObject;
import com.calvin.lib.notification.NotificationCenter;
import com.calvin.lingting.MainActivity;
import com.calvin.lingting.R;
import com.calvin.lingting.config.AppConfig;
import com.calvin.lingting.config.LrtsConfig;
import com.calvin.lingting.config.NTConfig;
import com.calvin.lingting.utils.Utils;

import java.io.File;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.Executor;

public class SerializationCenter implements NotificationCenter.OnNoticeListener {
    final String S_DATA = "data.dat";
    final String S_DOWNDLOAD = "dwonload.dat";
    final String S_LIKE = "like.dat";
    final String S_RECORD = "record.dat";
    private static SerializationCenter mInstance = null;
    static Executor mExecute = Utils.mExecutor;
    Handler mHandler = new Handler();

    JSONObject mBookList = null;

    JSONArray mDwonloadBookList = null;
    JSONArray mRecordBookList = null;
    JSONArray mLikeBook = null;
    Queue<Object[]> mQueueDwonload = new LinkedList<Object[]>();


    NotificationCompat.Builder mBuilder = null;
    String mFormatText = null;
    String mCurrentBookId = null;
    int mCurrentChapter = -1;

    long mTime = 0;

    private SerializationCenter() {
        mBuilder = new NotificationCompat.Builder(MainActivity.sharedCurrent());
        NotificationCenter.shared().addNotice(NTConfig.NT_DOWNLOAD_BOOK, this);
    }

    public static SerializationCenter shared() {
        return mInstance == null ? (mInstance = new SerializationCenter()) : mInstance;
    }

    public JSONObject getBookList() {
        return mBookList;
    }

    public JSONArray getDwonloadBookList() {
        JSONArray bookList = new JSONArray();
        Iterator<Object> iterator = mDwonloadBookList.iterator();
        while (iterator.hasNext()) {
            String bookId = (String) iterator.next();
            bookList.add(mBookList.getJSONObject(bookId));
        }
        return bookList;
    }

    public JSONArray getRecordBookList() {
        JSONArray bookList = new JSONArray();
        Iterator<Object> iterator = mRecordBookList.iterator();
        while (iterator.hasNext()) {
            String bookId = (String) iterator.next();
            bookList.add(mBookList.getJSONObject(bookId));
        }
        return bookList;
    }

    public JSONArray getLikeBookList() {
        JSONArray bookList = new JSONArray();
        Iterator<Object> iterator = mLikeBook.iterator();
        while (iterator.hasNext()) {
            String bookId = (String) iterator.next();
            bookList.add(mBookList.getJSONObject(bookId));
        }
        return bookList;
    }

    public void downloadBook(JSONObject bookInfo, final int chapter) {
        String bookId = bookInfo.getStringValue(LrtsConfig.K_BOOK_ID);
        if (!mBookList.containsKey(bookId)) {
            mBookList.put(bookId, bookInfo);
        }
        if (!mDwonloadBookList.contains(bookId)) {
            mDwonloadBookList.add(bookId);
        }
        mQueueDwonload.offer(new Object[]{
                bookId, chapter
        });
        if (mCurrentBookId == null) {
            downloadBook();
        }
    }

    private void downloadBook() {
        Object[] data = mQueueDwonload.poll();
        JSONObject bookInfo = mBookList.getJSONObject((mCurrentBookId = data[0].toString()));
        mCurrentChapter = (Integer) data[1];

        mBuilder.setSmallIcon(R.mipmap.ic_launcher);
        mBuilder.setContentTitle(bookInfo.getStringValue(LrtsConfig.K_NAME));
        mFormatText = MainActivity.sharedCurrent().getResources().getString(R.string.s_download_chapter);
        mFormatText = String.format(mFormatText, mCurrentChapter);
        final String url = bookInfo.getJSONObject(LrtsConfig.K_CHAPTER_LIST).getStringValue(mCurrentChapter + "");
        String ext = url.substring(url.length() - 4);
        final File outFile = Environment.getExternalStoragePublicDirectory(String.format("%s/%s/%s%s", AppConfig.SD_BOOK, bookInfo.getStringValue(LrtsConfig.K_NAME), mCurrentChapter, ext));
        mTime = System.currentTimeMillis();
        mExecute.execute(new Runnable() {
            @Override
            public void run() {
                Utils.downloadFile(url, outFile, NTConfig.NT_DOWNLOAD_BOOK);
            }
        });
    }


    private NotificationManager getNotificationManager() {
        return (NotificationManager) MainActivity.sharedCurrent().getSystemService(Context.NOTIFICATION_SERVICE);
    }

    public void addRecordBookList(JSONObject bookInfo) {
        String bookId = bookInfo.getStringValue(LrtsConfig.K_BOOK_ID);
        if (!mBookList.containsKey(bookId)) {
            mBookList.put(bookId, bookInfo);
        }
        if (mRecordBookList.contains(bookId)) {
            mRecordBookList.remove(bookId);
        }
        mRecordBookList.add(0, bookId);
    }

    public void addLikeBookList(JSONObject bookInfo) {
        String bookId = bookInfo.getStringValue(LrtsConfig.K_BOOK_ID);
        if (!mBookList.containsKey(bookId)) {
            mBookList.put(bookId, bookInfo);
        }
        if (!mLikeBook.contains(bookId)) {
            mLikeBook.add(0, bookId);
        }
    }

    public void serializationData() {
        String datPath = Environment.getExternalStoragePublicDirectory(AppConfig.SD_DATA).getPath();
        Utils.serialization(String.format("%s/%s", datPath, S_DATA), mBookList);
        Utils.serialization(String.format("%s/%s", datPath, S_RECORD), mRecordBookList);
        Utils.serialization(String.format("%s/%s", datPath, S_DOWNDLOAD), mDwonloadBookList);
        Utils.serialization(String.format("%s/%s", datPath, S_LIKE), mLikeBook);
    }

    public void serializationBookList() {
        String datPath = Environment.getExternalStoragePublicDirectory(AppConfig.SD_DATA).getPath();
        Utils.serialization(String.format("%s/%s", datPath, S_DATA), mBookList);
    }

    public void unSerializationData() {
        String datPath = Environment.getExternalStoragePublicDirectory(AppConfig.SD_DATA).getPath();
        mBookList = Utils.unSerialization(String.format("%s/%s", datPath, S_DATA), JSONObject.class);
        mRecordBookList = Utils.unSerialization(String.format("%s/%s", datPath, S_RECORD), JSONArray.class);
        mDwonloadBookList = Utils.unSerialization(String.format("%s/%s", datPath, S_DOWNDLOAD), JSONArray.class);
        mLikeBook = Utils.unSerialization(String.format("%s/%s", datPath, S_LIKE), JSONArray.class);
        mBookList = mBookList == null ? new JSONObject() : mBookList;
        mRecordBookList = mRecordBookList == null ? new JSONArray() : mRecordBookList;
        mDwonloadBookList = mDwonloadBookList == null ? new JSONArray() : mDwonloadBookList;
        mLikeBook = mLikeBook == null ? new JSONArray() : mLikeBook;
        Log.i("debug", mBookList.keySet().size() + "");
        Log.i("debug", mRecordBookList.size() + "");
        Log.i("debug", mDwonloadBookList.size() + "");
        Log.i("debug", mLikeBook.size() + "");
    }

    @Override
    public void onNotify(String notify, final Object... argv) {
        final int max = Integer.valueOf(argv[0].toString());
        final int cur = Integer.valueOf(argv[1].toString());
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                if (max == cur) {
                    JSONObject bookInfo = mBookList.getJSONObject(mCurrentBookId);
                    if (!bookInfo.containsKey(LrtsConfig.K_DOWNDLOAD)) {
                        bookInfo.put(LrtsConfig.K_DOWNDLOAD, new JSONArray());
                    }
                    Toast.makeText(MainActivity.sharedCurrent(), R.string.s_dwonload_success, Toast.LENGTH_SHORT).show();
                    bookInfo.getJSONArray(LrtsConfig.K_DOWNDLOAD).add(mCurrentChapter);
                    if (!mQueueDwonload.isEmpty()) {
                        downloadBook();
                    } else {
                        mCurrentChapter = -1;
                        mCurrentBookId = null;
                        getNotificationManager().cancel(NTConfig.SNT_DOWNLOAD_BOOK);
                    }
                } else {
                    if (System.currentTimeMillis() - mTime >= 200) {
                        mBuilder.setContentText(mFormatText + "-" + (int) (cur * 1.0 / max * 100) + "%   ");
                        mBuilder.setProgress(max, cur, false);
                        getNotificationManager().notify(NTConfig.SNT_DOWNLOAD_BOOK, mBuilder.build());
                        mTime = System.currentTimeMillis();
                    }
                }
            }
        });
    }
}
